<?php
/**
 * 默认系统级函数库文件
 */
class Core
{
	/** 系统配置，取值使用 Core::cfg() 方法 */
	static $convent	= array();

	/** array(Controller, action) */
	static $action	= array();

	static $APP_PATH	= APP_PATH;

	static $req_app	= null;

	static $track = true;

	/**
	 * 影响到controller.action执行方式的函数数组
	 * @var array
	 */
	static $action_hooks	= array(
		'before'	=>	null,	//中转到action前执行的方法
		'behind'	=>	null,	//成功执行action后执行的方法
		'reduce'	=>	null,	//core::action的替代执行方法
	);

	static $sent_session_id = false;
	
	/**
	 * 程序运行入口
	 */
	static function run()
	{
		if(!self::$sent_session_id && self::$convent['session']) {
			self::session();
		}

		$c	= strtok($_REQUEST['a'], '-');
		$a	= str_replace('-', '_', strtok(''));
		self::$action	= array($c,$a);
		
		if(self::$action_hooks['reduce']){
			call_user_func(self::$action_hooks['reduce'], $c, $a);
		}
		else
		{
			if(self::$action_hooks['before']){
				call_user_func(self::$action_hooks['before'], $c, $a);
			}
			self::action($c, $a);
			if(self::$action_hooks['behind']){
				call_user_func(self::$action_hooks['behind'], $c, $a);
			}
		}
	}

	/**
	 * 运行action前做一次过滤和其它设置
	 */
	static function prepro()
	{
		if(!empty($GLOBALS['SUBAPP'])){
			self::subapp($GLOBALS['SUBAPP']);
		}

		self::$convent	= array_merge(
				import('#/convent.php'),
				import(self::$APP_PATH.'/convent.php') );
		
		define('MOD_DEBUG',	self::$convent['debug']);

		header('Content-type: text/html; charset=utf-8');
		
		self::trackingErrors(true);

		ob_start(array(__CLASS__, 'outputFilter'));
		
		if(MOD_DEBUG) {
			ini_set('display_errors', '1');
			import('#/debug.php');
			set_error_handler(array(__CLASS__, '_errorHandler'), E_ALL);
			
			if(!file_exists(self::$APP_PATH. self::cfg('src_path'))) {
				Show::error('Source folder can`t be access!');
			}
			if( !file_exists(self::$APP_PATH. self::cfg('data_path'))
				|| !is_writeable(self::$APP_PATH. self::cfg('data_path')) ){
				Show::error('Data folder is not writeable!');
			}
		}
		else {
			ini_set('display_errors', '0');
			set_error_handler(array(__CLASS__, '_errorHandler'), E_ALL ^ E_NOTICE);
		}
		
		set_exception_handler(array(__CLASS__, '_exceptionHandler'));
		register_shutdown_function(array(__CLASS__, '_shutdownFunction'));

        if(preg_match('~^/(.*)\.php\b(.*)~', $_SERVER['REQUEST_URI'], $matches)){
            if($matches[2]){
                parse_str(substr($matches[2],1), $_GET);
                $_REQUEST = array_merge($_REQUEST, $_GET);
            }
            $method = !empty($_GET['method']) ? $_GET['method'] : 'show';
            $_REQUEST['a'] = str_replace('/','_',$matches[1]). "-{$method}";
        }
        else{
            $_query = substr($_SERVER['REQUEST_URI'], strlen(dirname($_SERVER['PHP_SELF'])));
            if('/'==$_query{0}) {
                $_query	= substr($_query, 1);
            }
            if($_query) {
                $_GET	= array();
                if($pos=strpos($_query, '?')) {
                    $_p	= parse_url($_query);
                    $_query	= $_p['path'].'/'.str_replace(array('&','='),'/',$_p['query']);
                }
                $tmp	= explode('/', $_query);
                $_REQUEST['a']	= array_shift($tmp);
                if($tmp) {
                    $c	= count($tmp);
                    if($c%2) {
                        $c++;
                        array_push($tmp, null);
                    }
                    for($i=0;$i<$c;$i+=2) {
                        if($tmp[$i]){
                            $_GET[$tmp[$i]]	= $tmp[$i+1];
                        }
                    }
                    $_REQUEST	= array_merge($_REQUEST, $_GET, $_POST);
                }
                unset($_query, $tmp);
            }
            else {
                if(!isset($_REQUEST['a'])) {
                    $_REQUEST['a']	= self::$convent['action'];
                }
            }
            if(false===strpos($_REQUEST['a'],'-')) {
                $_REQUEST['a']	.= '-show';
            }
            $_REQUEST['a']	= strtolower($_REQUEST['a']);
        }

		define('TPL_PATH',	self::$APP_PATH. self::$convent['tpl_path']);
		define('SRC_PATH',	self::$APP_PATH. self::$convent['src_path']);
		define('DATA_PATH',	self::$APP_PATH. self::$convent['data_path']);
		define('TMP_PATH',	DATA_PATH.'/tmp');

		if(($root = dirname($_SERVER['SCRIPT_NAME']))=='/') $root = '';
		define('WEB_ROOT',	self::$req_app ? '/'.self::$req_app : $root);
		define('WEB_THEME',	$root.self::$convent['tpl_path'].
								(View::theme()?'/'.View::theme():''));
		
	}

	/**
	  是否捕获出错信息
	  */
	static function trackingErrors($bool){
		if($bool){
			self::$track = true;
		}
		else{
			self::$track = false;
		}
	}

	/**
	 * 输出过滤
	 */
	static function outputFilter($string)
	{
		if(!$string) return '';
	
		if(self::$convent['vacua'])
		{
			static $vacua=null;
			if(null===$vacua) {
				$vacua	= false!==strpos(substr($string,0,100),'<!DOCTYPE ');
			}
			if($vacua) {
				//替换html空白符
				$string	= preg_replace('~(<.*>)[\s]+~m', '\1 ', $string);
				$string	= preg_replace('~<\!--(.*?)-->~m','', $string);
			}
		}
		
		if(!headers_sent()) {
			if(self::$convent['compress'] && function_exists('ob_gzhandler')) {
				$string	= ob_gzhandler($string, 1);
			}
		}
		
		return $string;
	}
	
	static function _shutdownFunction()
	{
		Db::close();
		
		//Log::write(1000*(microtime(true)-$GLOBALS['BTIME']));
		
		isset($GLOBALS['INC_LOG']) && Log::flush();
	}
	static function _errorHandler()
	{
		if(self::$track) {
			$err	= func_get_args();
			throw new ErrorException($err[1], $err[0], 0, $err[2], $err[3]);
		}
		else{
			return false;
		}
	}
	static function _exceptionHandler($e)
	{
		if(self::$track) {
			$errmsg	= strval($e);
			if(self::$convent['debug']) {
				Debug::pre($errmsg, 1, 0);
			}
			else {
				Log::error($errmsg);
				Show::go500($e->getMessage());
			}
		}
		else{
			return false;
		}
	}
	
	static function session()
	{
            //强制session扫描概率
//            ini_set('session.gc_probability', 1);
//            ini_set('session.gc_divisor', 100);
//            ini_set('session.cache_limiter', 'nocache');
            
            //date_default_timezone_set('PRC');
            
            self::$sent_session_id = true;

		if(self::$convent['session_name']) {
			session_name(self::$convent['session_name']);
		}

		if(!session_id()) {
			session_set_cookie_params(
				self::$convent['session_cookie_lifetime'],
				self::$convent['session_cookie_path'] ?: WEB_ROOT,
				self::$convent['session_cookie_domain']
				);
		}

		if(isset(self::$convent['session_lifetime'])) {
			ini_set('session.gc_maxlifetime', self::$convent['session_lifetime']);
		}
                
                if(isset(self::$convent['session_cookie_lifetime'])) {
			ini_set('session.cookie_lifetime', self::$convent['session_cookie_lifetime']);
		}
                session_cache_limiter('private,must-revalidate');
                session_start();

	}
	
	/**
	 * action选择器/依据提供给入口函数的参数，自动加载运行不同的action
	 */
	static function action($controller, $action, $sub=null)
	{
		$octl	= str_replace(' ','_',ucwords(str_replace('_',' ',$controller))).'Controller';
		if(method_exists($octl, $action)) {
			call_user_func(array(new $octl, $action));
		}
		else {
			Show::go400();
		}
	}
	
	/**
	 * 取系统行为配置信息
	 */
	static function cfg($key)
	{
		return self::$convent[$key];
	}

	private static function subapp($sets)
	{
		$app	= strtok($_SERVER['REQUEST_URI'], '/');
		$path	= '/'.strtok('');
		if(isset($sets[$app])) {
			self::$req_app	= $app;
			#为子应用改变环境变量
			self::$APP_PATH	.= "/{$sets[$app]}";
			$_SERVER['REQUEST_URI']		= "/{$sets[$app]}{$path}";
			$_SERVER['SCRIPT_NAME']		= "/{$sets[$app]}{$_SERVER['SCRIPT_NAME']}";
			$_SERVER['PHP_SELF']		= $_SERVER['SCRIPT_NAME'];
			$_SERVER['SCRIPT_FILENAME']	= 
						"{$_SERVER['DOCUMENT_ROOT']}{$_SERVER['SCRIPT_NAME']}";
			chdir(self::$APP_PATH);
		}
	}
}

function __autoload($class)
{
	if(app_cfg('autoload', $class)){
		import(app_cfg('autoload', $class));
	}
	else{
		switch($class)
		{
		case 'Db':
		case 'Model':
		case 'Show':
		case 'Html':
		case 'Log':
		case 'View':
			import('#/'.strtolower($class).'.php');
			break;
		default:
			if(false!==strpos('|StringHelper|PagerHelper|FilterHelper|ProofHelper|ImageHelper|', "|{$class}|")){
				import('#/helper/'.substr($class,0,-6).'.php');
				break;
			}
			if('Helper'===substr($class, -6)){
				import('$/helper/'.substr($class, 0, -6).'.php');
			}
			elseif('Controller'===substr($class, -10)){
				try{
					import('~/'.str_replace('_','/',strtolower(substr($class, 0, -10))).'.php');
				}
				catch(Exception $_){
					Show::go400();
				}
			}
			else{
				import('$/model/'.$class.'.php');
			}
		}
	}
}

?>
